#include "../lua/action_msg.h"
#include "gp_task.h"
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include <linux/un.h>
#include "msg_def.h"
#include <pthread.h>
#include <string.h>
#include "gp_layout_map.h"
#include "gp_dp1_ctl.h"
#include "gp_dp8_ctl.h"
#include "gp_subboard_ctl.h"
#include "gp_dj_ctl.h"
#include "gp_qpcr_ctl.h"
#include "resource_manage.h"

#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>


const moduleActFunc_internal actionFuncArr[MAX_STAGE_NUM] = 
{
    NULL,
    //dj_p_task_act_func,
    //dj_p_task_act_func,
    //dj_p_task_act_func,
    //dj_p_task_act_func,
        
};

CGpTask::CGpTask(int stageIn,int tube8Id):m_stageId(stageIn),m_tube8Id(tube8Id)
{
    switch (stageIn)
    {
        case STAGE_ADD_BREAKDOWN:
        {
            set_add_split_param();
			pthread_create(&m_threadHandle,NULL,threadFuncTask,this);
			pthread_join(m_threadHandle,NULL);
        }
        break;
        case STAGE_ADD_PROTAINASE:
        {

        }
        break;        
    }
    m_pstReagent = NULL;
    m_pstTube8Manage = NULL;
}

CGpTask::~CGpTask()
{
   if(paramMem)
   {
        char * ptrParamMem = (char*)paramMem;
        delete []ptrParamMem;

        paramMem = NULL;
   }
}

//pthread_mutex_t mutex_read_param = PTHREAD_MUTEX_INITIALIZER;

static xmlXPathObjectPtr getNodeset(xmlDocPtr pdoc, const xmlChar *xpath)
{
    xmlXPathContextPtr context = NULL; //定义XPath上下文指针
    context = xmlXPathNewContext(pdoc);//用xml文档指针来初始化context指针
    xmlXPathObjectPtr result = NULL; //定义XPath结果指针

    if (pdoc == NULL)
    {
        printf("pdoc is NULL\n");
        return NULL;
    }

    if (xpath)
    {
        if (context == NULL)
        {
            printf("context is NULL\n");
            return NULL;
        }

        result = xmlXPathEvalExpression(xpath, context);//计算xpath的查询结果，并存入result中
        xmlXPathFreeContext(context); 
        if (result == NULL)
        {
            printf("xmlXPathEvalExpression return NULL\n");
            return NULL;
        }


        if (xmlXPathNodeSetIsEmpty(result->nodesetval))
        //使用result->nodesetval得到节点集合指针，其中包含了所有符合Xpath查询结果的节点
        {
            xmlXPathFreeObject(result);//使用释放Xpath对象指针；
            printf("nodeset is empty\n");
            return NULL;
        }
    }

    return result;
}

int parseTraceLine(char * ptrStr, char * memInOut)
{
    signed char * ptrOneNode = (signed char*)memInOut;
    
    int numNodeResult = 0;
    int x = 0;
    int y = 0;
    int v = 0;
    unsigned short volume = 0;
    char * ptrSubStr = ptrStr;
    char * ptrSubStrTemp = ptrStr;
    int ret = sscanf(ptrSubStrTemp,"x%dy%dv%d",&x,&y,&v);
    if(ret < 3)
    {
        printf("sscanf ret is %d\n",ret);
        //return numNodeResult;
    }
    else
    {
        *ptrOneNode = (signed char)x;
        *(ptrOneNode+1) = (signed char)y;
        volume = (unsigned short)v;
        memcpy(ptrOneNode+2,&volume,sizeof(short));
        numNodeResult++;
        ptrOneNode += sizeof(int);
    }
    


    while((*ptrSubStr) != '\0')
    {
       ptrSubStr++;
       if((*ptrSubStr)==',')
       {
            ptrSubStrTemp = ptrSubStr + 1;
            ret = sscanf(ptrSubStrTemp,"x%dy%dv%d",&x,&y,&v);
            if(ret < 3)
            {
                printf("sscanf ret is %d\n",ret);
                continue;
            }

            *ptrOneNode = (signed char)x;
            *(ptrOneNode+1) = (signed char)y;
            volume = (unsigned short)v;
            memcpy(ptrOneNode+2,&volume,sizeof(short));
            numNodeResult++;
            ptrOneNode += sizeof(int);
       }
    }

    return numNodeResult;
}

int parseOneSuckSpit(xmlNodePtr pNodeSuckSpit, char * pMem)
{
    location_layout * pstSuckLoc = (location_layout *)(pMem + sizeof(int));
    
    //int * pSuckVolume = (int *)(pstSuckLoc + 1);

    location_layout * pstSpitLoc = (location_layout *)(pstSuckLoc + 1);

    //int * spitVolume = (int * )(pstSpitLoc+1);

    int *pTransType = (int * )(pstSpitLoc + 1);//suck1spit1, suck1spitm,suckmspitm,

    int *pLenSuck = pTransType + 1;

    int *pLenSpit = pLenSuck + 1;

    char * ptrCurr = (char*)(pLenSpit+1);

    xmlNodePtr pNodeSuckPos = NULL;
    xmlNodePtr pNodeSpitPos = NULL;
    xmlNodePtr pNodeTemp = xmlFirstElementChild(pNodeSuckSpit);
    xmlChar * ptrContent = NULL;
    int numSuck = 0;
    int numSpit = 0;

    char * ptrSpitStart = NULL;

    while(pNodeTemp)
    {
        if(!xmlStrcmp(pNodeTemp->name, BAD_CAST ("suck_pos")))
        {//pasrse the first suck pos.
            pNodeSuckPos = xmlFirstElementChild(pNodeTemp);
            while(pNodeSuckPos)
            {
                if(!xmlStrcmp(pNodeSuckPos->name, BAD_CAST ("x_column")))
                {
                    ptrContent = xmlNodeGetContent(pNodeSuckPos);
                    if(ptrContent)
                    {
                        pstSuckLoc->column_x = atoi((char*) ptrContent);
                        xmlFree(ptrContent);
                    }                        
                    //pnode = xmlNextElementSibling(pNodeSuckPos);
                    //continue;
                }
                else if(!xmlStrcmp(pNodeSuckPos->name, BAD_CAST ("y_row")))
                {
                    ptrContent = xmlNodeGetContent(pNodeSuckPos);
                    if(ptrContent)
                    {
                        pstSuckLoc->row_y = atoi((char*) ptrContent);
                        xmlFree(ptrContent);
                    }                        
                    //pnode = xmlNextElementSibling(pNodeSuckPos);
                }
                //pNodeSuckPos = pNodeSuckPos->next;
                pNodeSuckPos = xmlNextElementSibling(pNodeSuckPos);
            }
        }
        else if(!xmlStrcmp(pNodeTemp->name, BAD_CAST ("trace_suck")))
        {
            ptrContent = xmlNodeGetContent(pNodeTemp);
            if(ptrContent)
            {
                numSuck = parseTraceLine((char*)ptrContent, ptrCurr);
                xmlFree(ptrContent);
                if(numSuck>0)
                {
                    ptrCurr += (numSuck<<2);
                    ptrSpitStart = ptrCurr;
                }
            }
        }
        else if(!xmlStrcmp(pNodeTemp->name, BAD_CAST ("spit_pos")))
        {
            pNodeSpitPos = xmlFirstElementChild(pNodeTemp);
            while(pNodeSpitPos)
            {
                if(!xmlStrcmp(pNodeSpitPos->name, BAD_CAST ("x_column")))
                {
                    ptrContent = xmlNodeGetContent(pNodeSpitPos);
                    if(ptrContent)
                    {
                        pstSpitLoc->column_x = atoi((char*) ptrContent);
                        xmlFree(ptrContent);
                    }                        
                    //pnode = xmlNextElementSibling(pNodeSuckPos);
                    //continue;
                }
                else if(!xmlStrcmp(pNodeSpitPos->name, BAD_CAST ("y_row")))
                {
                    ptrContent = xmlNodeGetContent(pNodeSpitPos);
                    if(ptrContent)
                    {
                        //pstSpitLoc->indexY = atoi((char*) ptrContent);
                        pstSpitLoc->row_y = pstSpitLoc->indexY;
                        xmlFree(ptrContent);
                    }                        
                    //pnode = xmlNextElementSibling(pNodeSuckPos);
                }
                //pNodeSuckPos = pNodeSuckPos->next;
                pNodeSpitPos = xmlNextElementSibling(pNodeSpitPos);
            }
        }
        else if(!xmlStrcmp(pNodeTemp->name, BAD_CAST ("trace_spit")))
        {
            ptrContent = xmlNodeGetContent(pNodeTemp);
            if(ptrContent)
            {
                numSpit = parseTraceLine((char*)ptrContent, ptrCurr);
                xmlFree(ptrContent);
                if(numSpit>0)
                {
                    ptrCurr += (numSpit<<2);
                }
            }
        }
        //pNodeTemp = pNodeTemp->next;
        pNodeTemp = xmlNextElementSibling(pNodeTemp);
    }

    int ret = 0;
    if(numSuck>0&&numSpit>0)
    {
        if(numSuck==1 && numSpit==1)
        {
            *pTransType = SUCK1_SPIT1;
        }
        else if(numSuck==1 && numSpit>1)
        {
            *pTransType = SUCK1_SPITM;
        }
        else if(numSuck>1 && numSpit>1)
        {
            *pTransType = SUCKM_SPITM;
            if(numSuck != numSpit)
            {
                if(numSuck>numSpit)
                {
                    numSuck = numSpit;
                    char * ptrTemp = ptrSpitStart - ((numSuck-numSpit)<<2);
                    //ptrSpitStart -= ((numSuck-numSpit)<<2);
                    memmove(ptrTemp,ptrSpitStart,(numSpit<<2));
                }
                else if(numSuck<numSpit)
                {
                    numSpit = numSuck; 
                }
            }
        }
        ret = 0;
    }
    else
    {
        ret = 1;
    }
    
    
    *pLenSuck = numSuck;
    *pLenSpit = numSpit;

    return ret;
}

int read_liquid_trans_param(const char * fileNameIn, const char* pathInXml, void * paramOut,int *numParam)
{
    char * pParamMem =  (char *)paramOut;
    int * pPumpType = (int *)pParamMem;

    location_layout * pstSuckLoc = (location_layout *)(pParamMem + sizeof(int));
    
    location_layout * pstSpitLoc = pstSuckLoc + 1;

    int *pTransType = (int *)(pstSpitLoc + 1);//suck1spit1, suck1spitm,suckmspitm,

    int *pLenSuck = pTransType + 1;

    int *pLenSpit = pLenSuck + 1;

    char * pmemCurrPos = (char *)(pstSuckLoc); 

 
    
    xmlDocPtr pdoc = NULL; 

    xmlNodePtr proot = NULL;

    pdoc = xmlReadFile(fileNameIn,"UTF-8",0);//xmlParseFile(fileNameIn);

    proot = xmlDocGetRootElement(pdoc);

    if (proot == NULL) 
    {
        printf("error: file is empty!\n");
        xmlFreeDoc(pdoc);
        return 1;
    }

    xmlChar *xpath = BAD_CAST (pathInXml);

    xmlXPathObjectPtr result = getNodeset(pdoc, xpath);

    if (result == NULL)
    {
        printf("result is NULL\n");
        xmlFreeDoc(pdoc);
        return 2;
    }

    int paramNumTemp = 0;

    //printf("getNodeSet finished\n");

    xmlNodePtr pnode=NULL;
    
    int parseRet = 0;
    if(result)
    {
        pnode = xmlFirstElementChild(pnode);
        while(!pnode)
        {
            if(!xmlStrcmp(pnode->name, BAD_CAST ("suck_spit")))
            {
                //pmemCurrPos += 
                parseRet = parseOneSuckSpit(pnode, pmemCurrPos);
                if(!parseRet)
                {
                    char * ptrTemp = pmemCurrPos;
                    pmemCurrPos += sizeof(location_layout)*2;
                    pmemCurrPos += sizeof(int)*3;
                    pmemCurrPos += sizeof(int) * (*pLenSuck);
                    pmemCurrPos += sizeof(int) * (*pLenSpit);

                    memcpy(pmemCurrPos,ptrTemp,sizeof(location_layout)*2);
                    paramNumTemp ++;
                }
                pnode = pnode->next;
                continue;
            }
        }

        xmlXPathFreeObject(result); //释放结果指针
    }

    xmlFreeDoc(pdoc);
    xmlCleanupParser();
    xmlMemoryDump();

    *numParam = paramNumTemp;

    return 0; 
}

void CGpTask::set_add_split_param(void)
{
    paramMem = new char[MAX_TASK_PARAM_LEN];

	int pumpType = PUMP_5000UL;

    location_layout suckLoc;
    memset(&suckLoc,0,sizeof(location_layout));
    suckLoc.location_type = DJ_PURIFY_SPLIT;

    if(m_tube8Id < 16)
    {
        suckLoc.indexX = 0;
    }
    else
    {
        suckLoc.indexX = 1;
    }

    location_layout spitLoc;
    memset(&spitLoc,0,sizeof(location_layout));
    if(m_tube8Id<16)
    {
        spitLoc.location_type = DJ_PURIFY_8HOLES_A;
        spitLoc.indexX = m_tube8Id>>1;
        spitLoc.indexY = m_tube8Id%2;
    }
    else
    {
        spitLoc.location_type = DJ_PURIFY_8HOLES_B;
        spitLoc.indexX = (m_tube8Id-16)>>1;
        spitLoc.indexY = (m_tube8Id-16)%2;        
    }
    
    int memOffset = 0;
    char * pParamMem = (char *)paramMem;
    memcpy(pParamMem,&pumpType,sizeof(int));   
    memOffset += sizeof(int);

    memcpy(pParamMem+memOffset,&suckLoc,sizeof(location_layout));
    memOffset += sizeof(location_layout);

    memcpy(pParamMem+memOffset,&spitLoc,sizeof(location_layout));
    memOffset += sizeof(location_layout);    
    
    char fileName[256] = {0};
    if(m_tube8Id>16)
    {
        sprintf(fileName,"%s%d%s","/mnt/nanflash/apps/config/schemea/tube",
        m_tube8Id - 16,"dj_p_add.xml");
    }
    else
    {
        sprintf(fileName,"%s%d%s","/mnt/nanflash/apps/config/schemeb/tube",
        m_tube8Id,"dj_p_add.xml");        
    }
    int readRet = read_liquid_trans_param(fileName, "/dj_p/add_split", paramMem,&m_nodeNum);

    if(readRet!=0)
    {
        m_nodeNum = 0;
        return;
    }
	m_moduleId = MODULE_DJ_PURIFY;
	
}

void * threadFuncTask(void * paramIn)
{
    CGpTask * pGpTask = (CGpTask *)paramIn;
    pGpTask->start();
}

void CGpTask::set_action_param(void)
{
    switch (m_stageId)
    {
        case STAGE_ADD_BREAKDOWN:
        {
            set_add_split_param();
        }
        break;
        case STAGE_ADD_PROTAINASE:
        {
            set_add_split_param();
        }
        break;
        case STAGE_ADD_HELPDOWN:
        {
            set_add_split_param();
        }
        break;
        case STAGE_ADD_MAGNET:
        {
            set_add_split_param();
        }
        break;        
        default:
            break;
    }
}


int CGpTask::start(void)
{
    char * pmemParam = (char *)paramMem;

    set_action_param();
    
    //int act_type = *pstParam;
	//int len = *(pstParam+1);
    if(actionFuncArr[m_stageId])
    {
        actionFuncArr[m_stageId](pmemParam,this);
    }

    return 0;
	
}

int CGpTask::getRemainVolume(location_layout * plocIn, int isTube8)
{
    if(!isTube8)
    {
        if(m_pstReagent)
        {
            return m_pstReagent->getRemainVolume(m_moduleId,plocIn);
        }
        else 
        {
            return -1;
        }
    }
    else 
    {
        if(m_pstTube8Manage)
        {
            return m_pstTube8Manage->getRemainVolume(plocIn,m_tube8Id);
        }
        else 
        {
            return -1;
        }        
    }

}

void CGpTask::writeRemainVolume(location_layout * plocIn, int isTube8, int volumeToSet)
{
    if(!isTube8)
    {
        if(m_pstReagent)
        {
            m_pstReagent->setRemainVolume(m_moduleId,plocIn,volumeToSet);
        }
    }
    else 
    {
        if(m_pstTube8Manage)
        {
            m_pstTube8Manage->setRemainVolume(plocIn,m_tube8Id,volumeToSet);
        }        
    }
}

int dj_p_task_act_func(void * paramIn, CGpTask * pTask)
{
    char * pmemParam = (char *)paramIn;

    int * pPumpType = (int *)pmemParam;

    pmemParam += sizeof(int);
    location_layout * suckPos = (location_layout *)pmemParam;
    location_layout * spitPos = suckPos + 1;

    int * task_act_type = (int *)(spitPos+1);

    int * lenSuck = task_act_type + 1;
    int * lenSpit = lenSuck + 1;

    signed char * suckX = (signed char *)(lenSpit + 1);
    signed char * suckY = suckX + 1;

    unsigned short suckVolume = 0;
    memcpy(&suckVolume,suckY+1,2);

    int purifyCtl = 0x01;

    int actSuccess = 0;

    if((*task_act_type) == SUCK1_SPIT1 || SUCK1_SPITM == (*task_act_type))
    {
        int suckPrePos = 0;
        actSuccess = 0;
        CGpLayout * pstLayout = CGpLayout::get_instance();
        location_axis locAxis;
        suckPos->column_x += (*suckX);
        suckPos->row_y += (*suckY);
        suckPos->indexX = suckPos->column_x;
        suckPos->indexY = suckPos->row_y;
        suckPos->column_x = 0;
        suckPos->row_y = 0;
        int convertRet = pstLayout->convertToAxisLoc(suckPos,&locAxis);
        if(convertRet)
        {
            printf("djconvertSuckParam, convert location failed,errorNum:%d\n",convertRet);
        }
        else 
        {
            printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

            if((* pPumpType) == PUMP_250UL)
            {
                purifyCtl = 0x11;
            }
            else
            {
                purifyCtl = 0x01;
            }
            
            actSuccess = djXY_Move(&locAxis,purifyCtl);
        }
        dynamic_z zPos;
        pstLayout->getZloc_withoutConvert(Z_LOC_DJP_REAGENT,&zPos);
        
        int liquidType = VISCOSITY_LOW;
        if(suckPos->indexY == 6 || suckPos->indexY == 7)
        {
            liquidType = VISCOSITY_HIGH;
        }
        int volumeAir2 = djSuckCtlParam[liquidType].air2;

        if((*lenSpit) > 1)
        {
            volumeAir2 = 0;
        }

        int volumeRemain = 0;
        //calculate the liquid face height here
        volumeRemain = pTask->getRemainVolume(suckPos,0);
        if(volumeRemain == -1)
        {
            printf("remain volume is not enough\n");
            return 0;
        }

        float height = 0;
        volumeToHeight(volumeRemain,TUBE_BOTTOM_SEMISPHERE,&height);

        int deltaSteps = height * coeffmmToSteps_DJ_Z;
        int liquidFaceSteps = zPos.z_max - deltaSteps;


        suck_param tempSuckParam = {
        .posPre = zPos.z_tube_mouth, // this should be change according to the ----
        .speedPre = 20000, // the speed go to previous position
        .air1Quan = djSuckCtlParam[liquidType].air1, // the air quantity before suck liquid
        .speedDetect = 210,//20mm/s / 0.009525 = 209.973// the speed of detecting liquid face
        .threshold = 9, // the threshold of detecting
        .stepBelow = 10,// the step continue to go after detecting success
        .speedSuck = djSuckCtlParam[liquidType].speedSuck,// the suck speed
        .quantity = suckVolume, // the suck quantity
        .more = djSuckCtlParam[liquidType].liquidMore, // the reduntant quantity
        .posMax = zPos.z_max, //the max pos to go if no liquid ----this should be changed.
        .posPost = liquidFaceSteps,// this is calculated through the remain liquid volume.
        .speedPost = 210, // the speed to go to posPost,---equals to speedDetect
        .air2Quan = volumeAir2, // the air quantity after suck liquid    
        .spitQuan = djSuckCtlParam[liquidType].spitQuan, // spit back quantity
        .speedSuckAir1 = 50,//ul/s
        .delayAfterSuck = 1000, //ms
        .delayAfterSpit = 500, //ms
        .speedSuckAir2 = 50,//ul/s
        .spitSpeed = djSuckCtlParam[liquidType].spitSpeed,//inc/s
        };

        //actSuccess = dj_spit_once(&tempSuckParam, purifyCtl, 1);
        actSuccess = dj_suck(&tempSuckParam, purifyCtl);

        if(actSuccess!=1)
        {
            printf("dj p suck1 spit1, suck failed\n");
            return 0;
        }

        pTask->writeRemainVolume(suckPos,0,volumeRemain-suckVolume);

        //start spit here.
        char * pPosSpitMem = (char *)(suckX + (*lenSuck)* sizeof(int));
        signed char * spitX = (signed char *)pPosSpitMem;
        signed char * spitY = spitX + 1;

        unsigned short spitVolume = 0;
        int zGoZero = 0;

        for(int i=0;i<(*lenSpit);i++)
        {
            spitX = (signed char *)pPosSpitMem;
            spitY = spitX + 1;
            
            memcpy(&spitVolume,spitY+1,2);

            pPosSpitMem += 4;

            spitPos->row_y += (* spitY);

            convertRet = pstLayout->convertToAxisLoc(spitPos,&locAxis);
            if(convertRet)
            {
                printf("dj p suck1 spit1, convert location failed,errorNum:%d\n",convertRet);
            }
            else 
            {
                printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

                actSuccess = djXY_Move(&locAxis,purifyCtl);
            }
            
            if(actSuccess!=1)
            {
                printf("in djconvertSuckParam, x,y go to target location failed\n");
                return 0;
            }
            
            //char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
            //|xylayout|spitVolume|isformulti|remainVolume
            //int remainVolume = 1000;
            //read out the liquid type 

            volumeRemain = pTask->getRemainVolume(spitPos,1);

            //pstDataBuff += sizeof(int);
            //memcpy(&spitVolume,pstDataBuff,sizeof(int));

            int isForMulti = 0;
            //pstDataBuff += sizeof(int);
        // memcpy(&isForMulti,pstDataBuff,sizeof(int));

        // pstDataBuff += sizeof(int);
            //memcpy(&remainVolume,pstDataBuff,sizeof(int));


            printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,spitVolume,isForMulti);
            if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
            {
                printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
                liquidType = VISCOSITY_LOW;
            }

            volumeAir2 = djSuckCtlParam[liquidType].air2;
            int suckBackVolume = 5;

            int zlocValid = pstLayout->getZloc(spitPos->location_type,&zPos);
            if(!zlocValid)
            {
                printf("z location is not valid\n");
                return 0;
            }   
            
            printf("z tube mouth:%d,z max:%d\n",zPos.z_tube_mouth,zPos.z_max);

            int posPre = zPos.z_tube_mouth;

            //suck_param * pstSuckParam = (suck_param *)paramOut;
            
            float liquid_height = 0;
            convertRet = volumeToHeight(volumeRemain+spitVolume,TUBE_BOTTOM_SEMISPHERE,&liquid_height); 
            
            int deltaHeightSteps = liquid_height*coeffmmToSteps_DJ_Z;

            liquidFaceSteps = zPos.z_max - deltaHeightSteps;

            if(liquidFaceSteps<zPos.z_tube_mouth || liquidFaceSteps > zPos.z_max)
            {
                printf("djconvertSpitParam, liquid face height is invalid\n");
                return 0;
            }

            tecan_liquid_param spitParam = {
                .posPre = liquidFaceSteps,
                .posPost = zPos.z_tube_mouth,
                .posMax = zPos.z_max,
                .quantity = spitVolume, // the unit is uL
                .quanSpitAir1 = volumeAir2,//dp1SuckCtlParam[liquidType].air2,
                .quanSuckBack = suckBackVolume,
                .speed = 50,//400 ul/s * 40000inc/1000ul
                .delayAfterSpit = 300, // ms
                .speedGoUp = (int)(400*coeffmmToSteps_DJ_Z), // speed when go up back
                .speedSuckBack = 50,//speed suck back ul/s
            };


            zGoZero = (i==(*lenSpit)-1)?1:0;
            actSuccess = dj_spit_once(&spitParam, purifyCtl, zGoZero);
        }
    }

    return actSuccess;
}